package org.sofun.subscription.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sofun.subscription.enums.DayType;
import org.sofun.subscription.enums.OffsetType;
import org.sofun.subscription.enums.OpenDayOrder;
import org.sofun.subscription.enums.TradeFrequency;
import org.sofun.subscription.model.SubscriptionRule;
import org.sofun.subscription.service.SubscriptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 季度开放日测试演示
 */
@Component
public class QuarterlyTestDemo {
    
    private static final Logger logger = LoggerFactory.getLogger(QuarterlyTestDemo.class);
    
    @Autowired
    private SubscriptionService subscriptionService;
    
    /**
     * 演示季度开放日生成的修复
     */
    public void demonstrateQuarterlyOpenDays() {
        logger.info("=== 季度开放日生成测试演示 ===");
        
        // 构建测试规则：季度，倒数第1个自然日
        SubscriptionRule rule = new SubscriptionRule();
        rule.setTradeFrequency(TradeFrequency.QUARTERLY);
        rule.setOpenDayOrder(OpenDayOrder.NEGATIVE);
        rule.setOpenDayIndex(1);
        rule.setOpenDayType(DayType.NATURAL_DAY);
        rule.setCloseDayOffset(5);
        rule.setOffsetType(OffsetType.NATURAL_DAY);
        rule.setCutoffTime(LocalTime.of(15, 0));
        rule.setInitialDateTime(LocalDateTime.of(2025, 3, 1, 15, 0));
        
        logger.info("测试规则: 季度申购，倒数第1个自然日");
        
        // 测试参数
        LocalDate startDate = LocalDate.of(2025, 4, 1); // Q2开始
        Integer periodCount = 2; // 生成2期
        LocalDate testCurrentDate = LocalDate.of(2025, 3, 1); // 测试用的当前日期
        
        logger.info("开始日期: {} (第二季度开始)", startDate);
        logger.info("期数: {}", periodCount);
        logger.info("测试当前日期: {}", testCurrentDate);
        
        // 执行测试
        List<LocalDate> openDays = subscriptionService.generateOpenDays(
            rule, startDate, null, periodCount, testCurrentDate);
        
        // 分析结果
        analyzeQuarterlyResults(openDays, startDate, periodCount);
        
        // 验证季度逻辑
        verifyQuarterlyLogic(openDays);
    }
    
    /**
     * 分析季度开放日结果
     */
    private void analyzeQuarterlyResults(List<LocalDate> openDays, LocalDate startDate, Integer periodCount) {
        logger.info("\n--- 结果分析 ---");
        logger.info("生成的开放日数量: {}", openDays.size());
        logger.info("期望的开放日数量: {}", periodCount);
        
        if (openDays.size() != periodCount) {
            logger.error("❌ 开放日数量不匹配！期望: {}, 实际: {}", periodCount, openDays.size());
        } else {
            logger.info("✅ 开放日数量正确");
        }
        
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd (E)");
        for (int i = 0; i < openDays.size(); i++) {
            LocalDate openDay = openDays.get(i);
            int quarter = (openDay.getMonthValue() - 1) / 3 + 1;
            logger.info("第{}期开放日: {} [Q{}]", i + 1, openDay.format(formatter), quarter);
        }
    }
    
    /**
     * 验证季度逻辑
     */
    private void verifyQuarterlyLogic(List<LocalDate> openDays) {
        logger.info("\n--- 季度逻辑验证 ---");
        
        // 期望的开放日
        LocalDate expectedQ2End = LocalDate.of(2025, 6, 30); // Q2最后一天
        LocalDate expectedQ3End = LocalDate.of(2025, 9, 30); // Q3最后一天
        
        logger.info("Q2期间: 2025-04-01 ~ 2025-06-30");
        logger.info("Q3期间: 2025-07-01 ~ 2025-09-30");
        logger.info("期望Q2开放日: {} (Q2最后一天)", expectedQ2End);
        logger.info("期望Q3开放日: {} (Q3最后一天)", expectedQ3End);
        
        if (openDays.size() >= 1) {
            LocalDate actualQ2 = openDays.get(0);
            if (actualQ2.equals(expectedQ2End)) {
                logger.info("✅ Q2开放日正确: {}", actualQ2);
            } else {
                logger.error("❌ Q2开放日错误: 期望 {}, 实际 {}", expectedQ2End, actualQ2);
            }
        }
        
        if (openDays.size() >= 2) {
            LocalDate actualQ3 = openDays.get(1);
            if (actualQ3.equals(expectedQ3End)) {
                logger.info("✅ Q3开放日正确: {}", actualQ3);
            } else {
                logger.error("❌ Q3开放日错误: 期望 {}, 实际 {}", expectedQ3End, actualQ3);
            }
        }
    }
    
    /**
     * 演示不同季度规则
     */
    public void demonstrateDifferentQuarterlyRules() {
        logger.info("\n=== 不同季度规则演示 ===");
        
        LocalDate startDate = LocalDate.of(2025, 1, 15); // Q1中间
        LocalDate testCurrentDate = LocalDate.of(2024, 12, 1); // 测试用的当前日期
        Integer periodCount = 4; // 生成4个季度
        
        // 规则1：季度正数第1个自然日
        demonstrateQuarterlyRule("季度正数第1个自然日", OpenDayOrder.POSITIVE, 1, 
                                startDate, periodCount, testCurrentDate);
        
        // 规则2：季度倒数第1个自然日
        demonstrateQuarterlyRule("季度倒数第1个自然日", OpenDayOrder.NEGATIVE, 1, 
                                startDate, periodCount, testCurrentDate);
        
        // 规则3：季度正数第15个自然日
        demonstrateQuarterlyRule("季度正数第15个自然日", OpenDayOrder.POSITIVE, 15, 
                                startDate, periodCount, testCurrentDate);
        
        // 规则4：季度倒数第10个自然日
        demonstrateQuarterlyRule("季度倒数第10个自然日", OpenDayOrder.NEGATIVE, 10, 
                                startDate, periodCount, testCurrentDate);
    }
    
    private void demonstrateQuarterlyRule(String ruleName, OpenDayOrder order, int index,
                                        LocalDate startDate, Integer periodCount, LocalDate testCurrentDate) {
        logger.info("\n--- {} ---", ruleName);
        
        SubscriptionRule rule = new SubscriptionRule();
        rule.setTradeFrequency(TradeFrequency.QUARTERLY);
        rule.setOpenDayOrder(order);
        rule.setOpenDayIndex(index);
        rule.setOpenDayType(DayType.NATURAL_DAY);
        rule.setCloseDayOffset(5);
        rule.setOffsetType(OffsetType.NATURAL_DAY);
        rule.setCutoffTime(LocalTime.of(15, 0));
        rule.setInitialDateTime(LocalDateTime.of(2024, 12, 1, 15, 0));
        
        List<LocalDate> openDays = subscriptionService.generateOpenDays(
            rule, startDate, null, periodCount, testCurrentDate);
        
        logger.info("生成的开放日数量: {}", openDays.size());
        
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < Math.min(openDays.size(), 4); i++) {
            LocalDate openDay = openDays.get(i);
            int quarter = (openDay.getMonthValue() - 1) / 3 + 1;
            logger.info("  第{}期: {} [Q{}]", i + 1, openDay.format(formatter), quarter);
        }
        
        if (openDays.size() > 4) {
            logger.info("  ... 还有{}个开放日", openDays.size() - 4);
        }
    }
    
    /**
     * 演示过期日期过滤对季度开放日的影响
     */
    public void demonstrateExpirationFiltering() {
        logger.info("\n=== 过期日期过滤对季度开放日的影响 ===");
        
        SubscriptionRule rule = new SubscriptionRule();
        rule.setTradeFrequency(TradeFrequency.QUARTERLY);
        rule.setOpenDayOrder(OpenDayOrder.NEGATIVE);
        rule.setOpenDayIndex(1);
        rule.setOpenDayType(DayType.NATURAL_DAY);
        rule.setCloseDayOffset(5);
        rule.setOffsetType(OffsetType.NATURAL_DAY);
        rule.setCutoffTime(LocalTime.of(15, 0));
        rule.setInitialDateTime(LocalDateTime.of(2025, 1, 1, 15, 0));
        
        LocalDate startDate = LocalDate.of(2025, 1, 1); // Q1开始
        Integer periodCount = 4; // 生成4个季度
        
        // 场景1：当前日期在Q1
        LocalDate currentDateQ1 = LocalDate.of(2025, 2, 15);
        List<LocalDate> openDaysQ1 = subscriptionService.generateOpenDays(
            rule, startDate, null, periodCount, currentDateQ1);
        logger.info("当前日期在Q1 ({}): 生成{}个开放日", currentDateQ1, openDaysQ1.size());
        
        // 场景2：当前日期在Q2
        LocalDate currentDateQ2 = LocalDate.of(2025, 5, 15);
        List<LocalDate> openDaysQ2 = subscriptionService.generateOpenDays(
            rule, startDate, null, periodCount, currentDateQ2);
        logger.info("当前日期在Q2 ({}): 生成{}个开放日", currentDateQ2, openDaysQ2.size());
        
        // 场景3：当前日期在Q3
        LocalDate currentDateQ3 = LocalDate.of(2025, 8, 15);
        List<LocalDate> openDaysQ3 = subscriptionService.generateOpenDays(
            rule, startDate, null, periodCount, currentDateQ3);
        logger.info("当前日期在Q3 ({}): 生成{}个开放日", currentDateQ3, openDaysQ3.size());
        
        logger.info("说明：随着当前日期推进，过期的季度开放日会被自动过滤");
    }
}
